package com.test.security.springsecuritydemo4.controller;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.security.concurrent.DelegatingSecurityContextCallable;
import org.springframework.security.concurrent.DelegatingSecurityContextExecutorService;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * Created with IntelliJ IDEA.
 * Description:
 *
 * @author lzy
 * @since 2022/12/29 下午3:19
 */
@RestController
public class HelloController {
    private static final Logger LOGGER = LoggerFactory.getLogger(HelloController.class);

    @GetMapping("/hello")
    public String hello() {
        final SecurityContext context = SecurityContextHolder.getContext();
        final Authentication authentication = context.getAuthentication();

        return "Hello " + authentication.getName() + "!";
    }

    @Async
    @GetMapping("/hi")
    public String hi(Authentication auth) {
        LOGGER.info("Hi {}", auth.getName());
        return "Hi " + auth.getName() + "!";
    }

    @GetMapping("/ciao")
    public String ciao() {
        Callable<String> task = () -> {
            SecurityContext context = SecurityContextHolder.getContext();
            return context.getAuthentication().getName();
        };

        ExecutorService executorService = Executors.newCachedThreadPool();

        try {
            var contextTask = new DelegatingSecurityContextCallable<>(task);
            return "Ciao, " + executorService.submit(contextTask).get() + "!";
        } catch (InterruptedException | ExecutionException e) {
            LOGGER.error("error", e);
            return "error!";
        } finally {
            executorService.shutdown();
        }
    }

    @GetMapping("/ciao2")
    public String ciao2() {
        Callable<String> task = () -> {
            SecurityContext context = SecurityContextHolder.getContext();
            return context.getAuthentication().getName();
        };

        ExecutorService executorService = Executors.newCachedThreadPool();
        executorService = new DelegatingSecurityContextExecutorService(executorService);

        try {
            return "Ciao, " + executorService.submit(task).get() + "!";
        } catch (InterruptedException | ExecutionException e) {
            LOGGER.error("error", e);
            return "error!";
        } finally {
            executorService.shutdown();
        }
    }
}
